Input-Output 多路复用
IO 多路复用是使用 select 或 epoll、poll 同时箭筒多个 IO 事件,通过将多个 IO 请求交给内核进行监听。和 同步非阻塞 Input-Output 类似多路复用 IO 也需要轮询。负责 selec 状态查询的线程需要不断的对 select 进行轮询,当查出 select 下有 IO 操作就绪时进行 IO 操作,将数据从内核缓冲区复制到用户缓冲区
IO 多路复用流程
- 选择器注册。先将需要 read 操作的目标文件描述符(socket 连接)提前注册在选择器中,在 about_Java 中式 Selector 类。然后开启 IO 多路复用的轮询流程
- 就绪状态的轮询。通过选择器查询所有注册过的文件描述符的 IO 就绪状态。通过查询的系统调用,内核会返回一个就绪的 socket 列表。任何一个 socket 准备好了就代表内核缓存区有数据了。
- 用户线程获得就绪的 socket 列表后,根据其中的 socket 连接发起 read 调用,用户线程阻塞。内核将数据从内核缓冲区中复制到用户缓冲区。
- 复制完成后,内核返回结果,用户线程才会解除阻塞的状态,用户线程读取到了数据,继续执行
IO 多路复用的优点
- 可以同时处理多个 IO 事件,从而提高程序的并发性
- 一个线程可以处理多个 IO 事件,减少了系统调用和线程切换和维护的开销,提高了系统性能
IO 多路复用的缺点
本质上 select、epoll 系统效用还是阻塞的,属于同步 IO。需要在读写事件就绪后由系统调用本身负责读写,也就是说读写过程依然是阻塞的。要彻底的解除线程的阻塞,就必须使用 异步 Input-Output